package com.bandit.remoting.handler;

import com.bandit.exception.RpcException;
import com.bandit.factory.SingletonFactory;
import com.bandit.provider.ServiceProvider;
import com.bandit.provider.impl.ZKServiceProviderImpl;
import com.bandit.remoting.dto.RpcRequest;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * RpcRequest processor 处理RpcRequest <br>
 * 返回方法调用的结果 invokeTargetMethod()
 * @author Bandit
 * @create 2022/2/24 0:02
 */
@Slf4j
public class RpcRequestHandler {
    private final ServiceProvider serviceProvider;

    public RpcRequestHandler() {
        serviceProvider = SingletonFactory.getInstance(ZKServiceProviderImpl.class);
    }

    /**
     * 客户端发送 RpcRequest <br>
     * 服务端根据 RpcRequest中得到RpcServiceName <br>
     * 服务端运行这个服务通过 invokeTargetMethod() 返回结果给客户端
     * @param rpcRequest 客户端的RpcRequest请求
     * @return
     */
    public Object handle(RpcRequest rpcRequest) {
        Object service = serviceProvider.getService(rpcRequest.getRpcServiceName());
        return invokeTargetMethod(rpcRequest, service);
    }

    /**
     * 获得方法处理后的结果
     * @param rpcRequest 客户端request
     * @param service 服务对象
     * @return 目标方法的结果
     */
    private Object invokeTargetMethod(RpcRequest rpcRequest, Object service) {
        Object result;
        try {
            Method method = service.getClass().getMethod(rpcRequest.getMethodName(), rpcRequest.getParamTypes());
            result = method.invoke(service, rpcRequest.getParameters());
            log.info("service:[{}] successful invoke method:[{}]", rpcRequest.getInterfaceName(), rpcRequest.getMethodName());
        } catch (NoSuchMethodException | IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
            throw new RpcException(e.getMessage(), e);
        }
        return result;
    }
}
